using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Text;
using NSwag;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;

namespace LibKubernetesGenerator
{
    internal class VersionConverterAutoMapperGenerator
    {
        private readonly ClassNameHelper classNameHelper;

        public VersionConverterAutoMapperGenerator(ClassNameHelper classNameHelper)
        {
            this.classNameHelper = classNameHelper;
        }

        public void Generate(OpenApiDocument swagger, SourceProductionContext context, SyntaxTree manualconverter)
        {
            var allGeneratedModelClassNames = new List<string>();

            foreach (var kv in swagger.Definitions)
            {
                var def = kv.Value;
                var clz = classNameHelper.GetClassNameForSchemaDefinition(def);
                allGeneratedModelClassNames.Add(clz);
            }

            var manualMaps = new List<(string, string)>();

            manualMaps = Regex.Matches(manualconverter.GetText().ToString(), @"\.CreateMap<(?<T1>.+?),\s?(?<T2>.+?)>")
                .OfType<Match>()
                .Select(x => (x.Groups["T1"].Value, x.Groups["T2"].Value))
                .ToList();

            var versionRegex = @"(^V|v)[0-9]+((alpha|beta)[0-9]+)?";
            var typePairs = allGeneratedModelClassNames
                .OrderBy(x => x)
                .Select(x => new
                {
                    Version = Regex.Match(x, versionRegex).Value?.ToLower(),
                    Kinda = Regex.Replace(x, versionRegex, string.Empty),
                    Type = x,
                })
                .Where(x => !string.IsNullOrEmpty(x.Version))
                .GroupBy(x => x.Kinda)
                .Where(x => x.Count() > 1)
                .SelectMany(x =>
                    x.SelectMany((value, index) => x.Skip(index + 1), (first, second) => new { first, second }))
                .OrderBy(x => x.first.Kinda)
                .ThenBy(x => x.first.Version)
                .Select(x => (x.first.Type, x.second.Type))
                .ToList();

            var versionConverterPairs = typePairs.Except(manualMaps).ToList();

            var sbversion = new StringBuilder(@"// <auto-generated />
using AutoMapper;
using k8s.Models;

namespace k8s.ModelConverter.AutoMapper;

internal static partial class VersionConverter
    {
        private static void AutoConfigurations(IMapperConfigurationExpression cfg)
        {

");

            foreach (var (t0, t1) in versionConverterPairs)
            {
                sbversion.AppendLine($@"cfg.CreateMap<{t0}, {t1}>().ReverseMap();");
            }

            sbversion.AppendLine("}}");

            context.AddSource($"VersionConverter.g.cs", SourceText.From(sbversion.ToString(), Encoding.UTF8));
        }
    }
}
